﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
#if UNITY_IOS && !DEVELOP
using System.Runtime.InteropServices;
#endif
namespace QQSDK
{
    public class SDKManager : MonoBehaviour
    {
        public static SDKManager instance;
#if UNITY_EDITOR || DEVELOP

#elif UNITY_IOS && !DELSDK
        [DllImport("__Internal")]
        private static extern void initSDKWithConfig();
        [DllImport("__Internal")]
        private static extern void initAttribution();
        [DllImport("__Internal")]
        private static extern void initAnalytics(); 
        [DllImport("__Internal")]
        private static extern void appFlyerStart();
        [DllImport("__Internal")]
        private static extern void initMediation();
        [DllImport("__Internal")]
        private static extern void initAdsDisableAutoLoad(bool isAutoLoaded);
        [DllImport("__Internal")]
        private static extern void validateReceiptToServer(string url, string product_id, string sku_id, string transaction_id,string receipt, string purchase_point, string ext);
        [DllImport("__Internal")]
        private static extern void initNewAppFlyerWithAppId(string app_id, string dev_key);
        [DllImport("__Internal")]
        private static extern void newAppFlyerStart();
        //ABTest
        [DllImport("__Internal")]
        private static extern string getAB(string eXName);
        // [DllImport("__Internal")]
        //private static extern int initABTest(string ablist);
#elif UNITY_ANDROID
        private const string PACKAGE_NAME_Unity3d = "com.unity3d.player.UnityPlayer";
        public static AndroidJavaObject UnityActivity;

#if !DELSDK
        private const string PACKAGE_NAME_Control = "com.qq.control.QQSDKInit";
        private const string PACKAGE_NAME_Ads = "com.qq.control.QQSDKAds";
        private const string PACKAGE_NAME_Attribution = "com.qq.control.QQSDKAttribution";
        private const string PACKAGE_NAME_Analytics = "com.qq.control.QQSDKAnalytics";
        private const string PACKAGE_NAME_Tools = "com.qq.tools.ToolsUtil";

#endif
        public static AndroidJavaObject SDK_Control;
        public static AndroidJavaObject SDK_Ads;
        public static AndroidJavaObject SDK_Attribution;
        public static AndroidJavaObject SDK_Analytics;
        public static AndroidJavaObject SDK_Tools;


#elif UNITY_WEBGL

#else

#endif


        private void Awake()
        {
            DontDestroyOnLoad(gameObject);
            if (instance == null)
                instance = this;
#if UNITY_EDITOR || DEVELOP

#elif UNITY_IOS && !DELSDK

#elif UNITY_ANDROID
 
            UnityActivity = new AndroidJavaClass(PACKAGE_NAME_Unity3d).GetStatic<AndroidJavaObject>("currentActivity");
#if !DELSDK
            SDK_Control = new AndroidJavaClass(PACKAGE_NAME_Control).CallStatic<AndroidJavaObject>("instance");
            SDK_Tools = new AndroidJavaClass(PACKAGE_NAME_Tools);
            SDK_Ads = new AndroidJavaClass(PACKAGE_NAME_Ads).CallStatic<AndroidJavaObject>("instance");
            SDK_Attribution = new AndroidJavaClass(PACKAGE_NAME_Attribution).CallStatic<AndroidJavaObject>("instance");
            SDK_Analytics = new AndroidJavaClass(PACKAGE_NAME_Analytics).CallStatic<AndroidJavaObject>("instance");

         
#endif
#elif UNITY_WEBGL

#else
#endif
            ToolsManager.Set();
            AnalyticsManager.Set();
            AdsManager.instance.Set();
            AttributionManager.Set();

            FireBaseManager.Set();

        }

        /// <summary>
        /// 初始化广告，数仓，工具等
        /// </summary>
        public static void Init()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initSDKWithConfig();
#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("init",GetCurrentlyActivity());
            }
#else
#endif
        }

        /// <summary>
        /// 单独初始化数仓(当手动初始化广告时，可调用此接口，不可与Init接口同时调用)
        /// </summary>
        public static void InitAnalytics()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initAnalytics();
#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("initAnalytics");
            }
#else
#endif
        }

        static Dictionary<string, string> ABCacheData = new Dictionary<string, string>();
        /// <summary>
        /// 通过实验名获取分配的组名称
        /// </summary>
        /// <param name="eXName">实验名称</param>
        /// <returns>
        /// 返回noinit:表示没有初始化,需要延迟重新再获取, 
        /// 返回noset: 表示没有分配到组
        /// 返回a/b/c/d/e/f:表示具体的组名
        /// </returns>

        public static string GetABTest(string eXName)
        {
            //if (!ConfigIsInit)
            //{
            //    return "noinit";
            //}
            if(ABCacheData.ContainsKey(eXName))
            {
                return ABCacheData[eXName];
            }
            string abTest = string.Empty;
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            abTest = getAB(eXName);
#elif UNITY_ANDROID
            if (SDK_Control != null)
                abTest = SDK_Control.Call<string>("getAB",eXName);
#else
#endif
            if (abTest.Length > 0 && abTest != "noinit" && !ABCacheData.ContainsKey(eXName))
            {
                ABCacheData.Add(eXName, abTest);
            }
            return abTest;
        }

//        public static bool ConfigIsInit = false;
//        public static int ConfigTryTimes = 10; //最大试错10次
//        /// <summary>
//        /// 配置请求并初始化, 只初始化传入的abtest组名称, 如果网络没问题, 会每间隔3秒重试10次(可调用接口修改)
//        /// </summary>
//        /// <param name="ablist">abtest的所有实验名称</param>
//        /// <returns></returns>
//        public IEnumerator InitConfig(List<string> ablist)
//        {
//            if (ConfigTryTimes-- > 0)
//            {
//                GetServerConfig(ablist);

//                if (!ConfigIsInit)
//                {//:延迟3s调用, 防止网络还未获取到配表
//                    yield return new WaitForSeconds(3f);
//                    StartCoroutine(InitConfig(ablist));
//                }
//            }
//        }
//        /// <summary>
//        /// InitABTest
//        /// </summary>
//        private void GetServerConfig(List<string> eXNameList)
//        {
//            string ablist = JsonMapper.ToJson(eXNameList);
//#if UNITY_EDITOR || DEVELOP
//#elif UNITY_IOS && !DELSDK
//            abTestIsInit = initABTest(ablist) == 1;
//#elif UNITY_ANDROID
//            if (SDK_Control != null)
//               abTestIsInit = SDK_Control.Call<string>("initABtest",ablist) == 1;
//#else
//#endif
//            SDKFunc.Log("ablist:" + ablist + " TryTimes : " + ConfigTryTimes + " init :"+ ConfigIsInit);

//            ConfigIsInit = false;
//        }

        /// <summary>
        /// 初始化归因
        /// </summary>
        public static void InitAttribution()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initAttribution();
#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("initAttribution");
            }
#else
#endif
        }

        /// <summary>
        /// 启动af 
        /// </summary>
        public static void AppFlyerStart()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            appFlyerStart();
#elif UNITY_ANDROID    
#else
#endif
        }

        /// <summary>
        /// 初始化af(reyun + af) 
        /// </summary>
        public static void InitNewAppFlyer(string app_id, string dev_key)
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initNewAppFlyerWithAppId(app_id,dev_key);
#elif UNITY_ANDROID    
#else
#endif
        }

        /// <summary>
        /// 启动af(reyun + af) 
        /// </summary>
        public static void NewAppFlyerStart()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            newAppFlyerStart();
#elif UNITY_ANDROID    
#else
#endif
        }

        /// <summary>
        /// 单独初始化广告(当需要单独初始化广告时，可调用此接口，不可与Init接口同时调用)
        /// </summary>
        public static void initAds()
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initMediation();
#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("initAds",GetCurrentlyActivity());
            }
#else
#endif
        }

        /// <summary>
        /// 单独初始化广告(当手动初始化广告时，可调用此接口，不可与Init接口同时调用)
        ///  isAutoLoaded : true 自动加载广告 false:手动加载广告
        /// </summary>
        public static void InitAds(bool isAutoLoaded)
        {
#if UNITY_EDITOR || DEVELOP
#elif UNITY_IOS && !DELSDK
            initAdsDisableAutoLoad(isAutoLoaded);
#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("initAds",GetCurrentlyActivity(),isAutoLoaded);
            }
#else
#endif
        }

        public static AndroidJavaObject GetCurrentlyActivity()
        {
#if UNITY_EDITOR || DEVELOP
            return null;
#elif UNITY_ANDROID
            return UnityActivity;
#else
            return null;
#endif

        }
        private static AndroidJavaObject G_GetContext = null;
        public static AndroidJavaObject GetContext()
        {
#if UNITY_EDITOR || DEVELOP
            return null;

#elif UNITY_ANDROID
            if(UnityActivity != null)
            {
                if(G_GetContext == null)
                {
                    G_GetContext = UnityActivity.Call<AndroidJavaObject>("getApplicationContext");
                }
                return G_GetContext;
            }
            else
            {
                return null;
            }
#else
            return null;
#endif

        }

        #region 订阅接口验证和回调

        //支付回调接口
        public static UnityEngine.Events.UnityAction<PurchaseCallBackData> onPayResultMessageCallback;

        /// <summary>
        /// 订阅验证接口Android
        /// </summary>
        /// <param name="product_id">产品id</param>
        /// <param name="token">订单token</param>
        /// <param name="order_type">订阅类型 1:一次性购买 2：订阅类</param>
        public static void PurchaseVerification_Android(string product_id, string token, int order_type)
        {
            SDKFunc.Log("PurchaseVerification:" + product_id + ",order_type=" + order_type);
#if UNITY_EDITOR || DEVELOP
            DealPurchaseVerificationCallBack(@"{ ""product_id"" : ""small_diamonds"",  ""message"" : ""{\""code\"":6000,\""msg\"":\""处理完成\"",\""records\"":{\""purchaseTime\"":\""2022-11-28T14:52:35.259\"",\""purchaseState\"":\""0\"",\""consumptionState\"":\""0\"",\""developerPayload\"":\""\"",\""orderId\"":\""GPA.3314-3542-5698-07117\"",\""acknowledgementState\"":\""0\"",\""kind\"":\""androidpublisher#productPurchase\"",\""regionCode\"":\""SG\"",\""packageName\"":\""com.***.merge\"",\""productId\"":\""small_diamonds\"",\""checkNum\"":1}}"",  ""state"" : ""1"",  ""platform"" : ""ios""}");//test call back
#elif UNITY_IOS && !DELSDK

#elif UNITY_ANDROID
            if(SDK_Control != null)
            {
                SDK_Control.Call("purchaseVerification", product_id, token, order_type);
            }
#else
          
#endif

        }

        /// <summary>
        ///  订阅验证接口IOS
        ///  请注意*********************使用该接口，必须在中台上传IOS的内购验证秘钥*********************
        /// </summary>
        /// <param name="product_id">内购id</param>
        /// <param name="sku_id">"IAP AppleID", 例子 : Piczoo2 的  Yearly Premium sku_id: 1457947282</param>
        /// <param name="transaction_id">交易id </param>
        /// <param name="receipt">苹果的交易凭据</param>
        /// <param name="purchase_point">购买点位</param>
        /// <param name="ext">扩展信息，没有填空字符串</param>
        public static void PurchaseVerification_IOS(string product_id, string sku_id, string transaction_id, string receipt, string purchase_point, string ext)
        {
            if (receipt.Contains("Payload") && receipt.Contains("TransactionID"))
            {//说明数据是Unity的回传，没有加工
                UnityIOSPayData unityIOSPayData = JsonMapper.ToObject<UnityIOSPayData>(receipt);
                if (unityIOSPayData.Payload.Length > 0)
                {
                    receipt = unityIOSPayData.Payload;
                }
                SDKFunc.Log("ChangePayData:" + receipt);
            }
            string url = "https://subscription.tapque.com/api/device/subscribe";
#if UNITY_EDITOR || DEVELOP
            DealPurchaseVerificationCallBack(@"{ ""product_id"" : ""small_diamonds"",  ""message"" : ""{\""code\"":\""6000\"",\""data\"":{\""originalTransactionId\"":\""2000000295083072\"",\""receiptType\"":\""ProductionSandbox\"",\""isTrialPeriod\"":\""false\"",\""downloadId\"":\""0\"",\""transactionId\"":\""2000000295083072\""}}"",  ""state"" : ""1"",  ""platform"" : ""ios""}");//test call back
#elif UNITY_ANDROID

#elif UNITY_IOS && !DELSDK
            validateReceiptToServer(url, product_id, sku_id, transaction_id, receipt , purchase_point, ext);
#endif
        }

        /// <summary>
        /// IOS订阅验证回调
        /// </summary>
        /// <param name="data"></param>
        public static void DealPurchaseVerificationCallBack(string data)
        {
            SDKFunc.Log("iap回调:"+ data);
            if (data.Contains("platform") && data.Contains("product_id"))
            {

#if UNITY_EDITOR || DEVELOP
                //IOSPlayPurchaseCallBack ippcb = JsonMapper.ToObject<IOSPlayPurchaseCallBack>(data);
                //onPayResultMessageCallback?.Invoke(ippcb.toPurchaseCallBack());
                //return;
#elif UNITY_IOS && !DELSDK

                IOSPlayPurchaseCallBack ippcb = JsonMapper.ToObject<IOSPlayPurchaseCallBack>(data);
                onPayResultMessageCallback?.Invoke(ippcb.toPurchaseCallBack());
                return;
#elif UNITY_ANDROID
                GooglePlayPurchaseCallBack gppcb = JsonMapper.ToObject<GooglePlayPurchaseCallBack>(data);
                onPayResultMessageCallback?.Invoke(gppcb.toPurchaseCallBack());
                return;
#else
          
#endif
            }

            PurchaseCallBackData pcbdD = new PurchaseCallBackData();
            pcbdD.state = PurchaseState.Error;
            onPayResultMessageCallback?.Invoke(pcbdD);
            return;
        }



        #endregion

        public class UnityCallBackData
        {
            public string m = "";
            public string d = "";
        }

        public enum MethodName
        {
            Callback,
            ImpressionCallback,
            ReyunAttributionCallback,
            ReyunIdCallback,
            GetIDCallback,
            RewardSecretKeyCallback,
            AttributionObject,
            SetLogLevel,
            IapCallback,
            AfUaMessageCallback,
            AfIPMessageCallback,
        }

        public void CommCallback(string message)
        {
            SDKFunc.Log("CommCallback" + message);
            UnityCallBackData unityCallBackData = JsonMapper.ToObject<UnityCallBackData>(message);
            //SDKFunc.Log("CommCallback：" + unityCallBackData.m);
            //SDKFunc.Log("CommCallback：" + unityCallBackData.d);
            if (unityCallBackData.m == MethodName.Callback.ToString())
            {
                AdsManager.instance.Callback(unityCallBackData.d);
            }

            else if (unityCallBackData.m == MethodName.ImpressionCallback.ToString())
            {
                AdsManager.instance.ImpressionCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.ReyunAttributionCallback.ToString())
            {
                AdsManager.instance.ReyunAttributionCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.ReyunIdCallback.ToString())
            {
            }
            else if (unityCallBackData.m == MethodName.GetIDCallback.ToString())
            {
            }
            else if (unityCallBackData.m == MethodName.RewardSecretKeyCallback.ToString())
            {
                AdsManager.instance.RewardSecretKeyCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.AttributionObject.ToString())
            {
                AdsManager.instance.AttributionDataCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.SetLogLevel.ToString())
            {
                ToolsManager.SetLogLevel(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.AfUaMessageCallback.ToString())
            {
                AdsManager.instance.AfUaMessageCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.AfIPMessageCallback.ToString())
            {
                AdsManager.instance.AfIPMessageCallback(unityCallBackData.d);
            }
            else if (unityCallBackData.m == MethodName.IapCallback.ToString())
            {
                DealPurchaseVerificationCallBack(unityCallBackData.d); 
            }
            //case MethodName.ReyunIdCallback.ToString():
            //    AdsManager.instance.Callback(unityCallBackData.d);
            //    break;

            //case MethodName.GetIDCallback.ToString():
            //    AdsManager.instance.Callback(unityCallBackData.d);
            //    break;
        }

    }
}